#include "devInfo.h"
#include <fal.h>
#include <sfud.h>
#include <dfs_fs.h>
#include "comm.h"
#include <unistd.h>

#define DBG_LEVEL DBG_INFO
#define DBG_SECTION_NAME  "devinfo.c"
#include <rtdbg.h>

static devInfoDef devinfo = {0,};
static rt_mutex_t devInfoMux = RT_NULL;//线程安全用
static appConfigDef appConfig;//应用配置，会保存到文件
static rt_uint8_t infoMuxCnt = 0;

/* ----------------------------------------------------------------------------*/
/**
 * @brief take_devInfo      拿设备信息
 *
 * @return    返回设备信息地址
 */
/* ----------------------------------------------------------------------------*/
devInfoDef* devInfo_take(void)
{
	rt_err_t result;
	
	if(devInfoMux == RT_NULL)
	{
		devInfoMux = rt_mutex_create("info", RT_IPC_FLAG_FIFO);
		infoMuxCnt = 0;
	}
	RT_ASSERT(devInfoMux);

	result = rt_mutex_take(devInfoMux, 1000);
	if(result != RT_EOK)
	{
		rt_kprintf("take devinfo outtime\r\n");
		rt_mutex_take(devInfoMux, RT_WAITING_FOREVER);
	}
	infoMuxCnt++;
	return &devinfo;
}


/* ----------------------------------------------------------------------------*/
/**
 * @brief release_devinfo       释放设备信息
 */
/* ----------------------------------------------------------------------------*/
void devinfo_release(void)
{
	infoMuxCnt--;
	if(infoMuxCnt)
	{
		LOG_E("devinfo Mux Cnt %d!!!!!!!!!!!!!!!!",infoMuxCnt);
	}
	rt_mutex_release(devInfoMux);
}


static void store_crc_get(storDataCrcDef *store)
{
	rt_uint8_t *buf;
	rt_uint16_t crc;
	
	buf = (rt_uint8_t *)store;
	crc = CRC16_MODBUS(buf, sizeof(*store)-2);	
	store->crc16 = crc;
}

/* ----------------------------------------------------------------------------*/
/**
 * @brief devInfo_init      设备信息初始化
 */
/* ----------------------------------------------------------------------------*/
void devInfo_init(void)
{
	devInfoDef *info;

	info = devInfo_take();
	devinfo_release();

	if(info->saveFlag != DEVINFO_SAVE_FLAG)//没有初始化过
	{
		rt_memset(info,0,sizeof(*info));
		info->netType = NET_TYPE_WIFI;//默认4G
		info->heartCyc = 60;
		info->serverType = 1;//默认使用TCP协议

		rt_strcpy((char *)(info->tcpCFG.url),SERVER_URL_STR);//设置默认网址
		info->tcpCFG.port = SERVER_URL_PORT;
		rt_strcpy((char *)(info->mqttCFG.url),MQTT_URL_STR);
		rt_strcpy((char *)(info->mqttCFG.port),MQTT_PORT_STR);
		rt_strcpy((char *)(info->mqttCFG.account),MQTT_ACCOUNT_STR);
		rt_strcpy((char *)(info->mqttCFG.pwd),MQTT_PW_STR);//默认密码
		rt_kprintf("%s\r\n",MQTT_PUBLISH_STR);
		rt_strcpy((char *)(info->mqttCFG.publish),MQTT_PUBLISH_STR);//默认密码
		rt_kprintf("%s\r\n",info->mqttCFG.publish);
		rt_strcpy((char *)(info->mqttCFG.subscribe),MQTT_SUBSCRIBE_STR);//默认密码

		info->data.centerMotorA.status = 1;
		info->data.centerMotorB.status = 1;
		info->data.lifter.status = 1;
		info->data.skylight.status = 1;
		info->data.SwichUAV.status = 1;
		info->data.SwitchCharge.status = 1;
		info->data.SwitchRC.status = 1;
		
		save_devinfo();
	}
	else//已经初始化过了
	{
	}

	info->PCBType = 4;
	get_mcu_mac();
	show_devinfo();
}


void devInfo_clean(void)
{
	devInfoDef *info;

	info = devInfo_take();
	devinfo_release();

	info->eStop = 0;
	info->data.BatTemp.data = 0;
	info->data.windDir.data = 0;
	info->data.windSpeed.data = 0;

	info->tempData.PTCTemp = 0;
	info->tempData.setPTC = 10;
	info->tempData.temp1 = 25;
	info->tempData.temp2 = 26;
	info->tempData.temp3 = 27;
}


appConfigDef *appConfig_take(void)
{
	return &appConfig;
}


void appConfig_release(void)
{

}

void appConfig_init(void)
{
	appConfigDef *sinfo;
	//rt_uint8_t   i;
	sinfo = appConfig_take();

	sinfo->saveFlag = DEVINFO_SAVE_FLAG;
	rt_strncpy((char *)(sinfo->wifi.ssid), "ELS_AP", sizeof("ELS_AP"));
	rt_strncpy((char *)(sinfo->wifi.pwd), "nsq123456", sizeof("nsq123456"));

	appConfig_release();
}

void appConfig_clean(void)
{
	appConfigDef *sinfo;
	//rt_uint8_t   i;
	sinfo = appConfig_take();	

	appConfig_release();
}

void appConfig_show(void)
{
	appConfigDef *sinfo;
	//rt_uint8_t i;
	//rt_uint8_t j;

	sinfo = appConfig_take();
	rt_kprintf("##########################################################################\n");
	rt_kprintf("app->wifi.ssid = %s\r\n",sinfo->wifi.ssid);
	rt_kprintf("app->wifi.pwd  = %s\r\n",sinfo->wifi.pwd);
	
	rt_kprintf("##########################################################################\n");
}

rt_err_t save_appConfig(void)
{
	rt_err_t result;
	int fd, size;
	appConfigDef *sinfo;
	appCfgStoreDef *flash;

	flash = rt_calloc(1, sizeof(*flash));

	sinfo = appConfig_take();
	sinfo->saveFlag = DEVINFO_SAVE_FLAG;
	rt_memcpy(&(flash->arg),sinfo,sizeof(*sinfo));//拷贝数据到存储结构
	store_crc_get(&(flash->stor));//计算CRC
	rt_kprintf("save_appConfig CRC=%X\r\n",flash->stor.crc16);
	appConfig_release();
	
	fd = open(APPCNF_FILE_NAME, O_RDWR | O_CREAT | O_TRUNC);
	if(fd >= 0)//打开成功
	{
		size = write(fd,flash,sizeof(*flash));
		if(size == sizeof(*flash))//写成功
		{
			rt_kprintf("sizeof(*flash) = %d\r\n",sizeof(*flash));
			result = RT_EOK;
		}
		close(fd);
	}
	else
	{
		rt_kprintf("save %s file fail !!!\r\n",APPCNF_FILE_NAME);
		result = RT_ERROR;
	}

	rt_free(flash);
	return result;
}

rt_err_t load_appConfig(void)
{
	rt_err_t result;
	int fd, size;
	appConfigDef *sinfo;
	appCfgStoreDef *flash;

	flash = rt_calloc(1, sizeof(*flash));

	fd = open(APPCNF_FILE_NAME, O_RDWR);
	if(fd >= 0)//打开文件成功
	{	
		rt_uint16_t crc16;
		
		read(fd,flash,sizeof(*flash));

		crc16 = flash->stor.crc16;
		store_crc_get(&(flash->stor));

		if(crc16 == flash->stor.crc16)
		{
			sinfo = appConfig_take();
			rt_memcpy(sinfo,&(flash->arg),sizeof(*sinfo));
			appConfig_release();
		}
		else
		{
			appConfig_init();
			LOG_E("load_appConfig CRC err %x != %x,using default config",crc16,flash->stor.crc16);
		}

		close(fd);
		result = RT_EOK;
		rt_kprintf("load %s file ok ^_^\r\n",APPCNF_FILE_NAME);
	}
	else
	{
		appConfig_init();
		rt_kprintf("load %s file fail !!!\r\n",APPCNF_FILE_NAME);
		result = RT_ERROR;
	}

	rt_free(flash);
	return result;
}


/* ----------------------------------------------------------------------------*/
/**
 * @brief show_devinfo      设备信息显示
 */
/* ----------------------------------------------------------------------------*/
void show_devinfo(void)
{
	devInfoDef *dev;

	dev = devInfo_take();
	
	rt_kprintf("################################devInfoDef = %d##########################\n",sizeof(*dev));
	rt_kprintf("dev->url                 = %s\r\n",dev->tcpCFG.url);
	rt_kprintf("dev->port                = %d\r\n",dev->tcpCFG.port);
	rt_kprintf("dev->saveFlag            = %x\r\n",dev->saveFlag);
	rt_kprintf("dev->data.vbat           = %d\r\n",dev->data.vbat);
	rt_kprintf("dev->data.temp           = %d\r\n",dev->data.temp);
	rt_kprintf("dev->heartCyc            = %d\r\n",dev->heartCyc);
	rt_kprintf("dev->netStatus           = %d\r\n",dev->netStatus);
	rt_kprintf("dev->saveFlag            = %d\r\n",dev->saveFlag);
	rt_kprintf("dev->data.vbat           = %8d\r\n",dev->data.vbat);
	rt_kprintf("dev->data.csq            = %8d\r\n",dev->data.csq);
	rt_kprintf("dev->data.date           = %d\r\n",dev->data.date);
	rt_kprintf("dev->netType             = %d\r\n",dev->netType);
	rt_kprintf("dev->mqttCFG.url         = %s\r\n",dev->mqttCFG.url);
	rt_kprintf("dev->mqttCFG.port        = %s\r\n",dev->mqttCFG.port);
	rt_kprintf("dev->mqttCFG.pwd         = %s\r\n",dev->mqttCFG.pwd);
	rt_kprintf("dev->mqttCFG.publish     = %s\r\n",dev->mqttCFG.publish);
	rt_kprintf("dev->mqttCFG.subscribe   = %s\r\n",dev->mqttCFG.subscribe);
	rt_kprintf("dev->centerMotorA.status = %d\r\n",dev->data.centerMotorA.status);
	rt_kprintf("dev->centerMotorB.status = %d\r\n",dev->data.centerMotorB.status);
	rt_kprintf("dev->lifter.status       = %d\r\n",dev->data.lifter.status);
	rt_kprintf("dev->skylight.status     = %d\r\n",dev->data.skylight.status);
	rt_kprintf("dev->SwichUAV.status     = %d\r\n",dev->data.SwichUAV.status);
	rt_kprintf("###################################################################\n");

	devinfo_release();
}

#define FAL_DEVINFO_NAME "devinfo"
#define DEVINFO_CFG_BAT  "/devinfo.CFG"

static void copy_info_to_file(void)
{
	struct fal_partition *fal;
	devInfoStoreDef      *flash;
	
	flash = rt_calloc(1, sizeof(*flash));
	RT_ASSERT(flash);

	fal = fal_partition_find((const char *)FAL_DEVINFO_NAME);
	if(fal != RT_NULL)
	{
		int rsize;
		
		rsize = fal_partition_read(fal, 0, flash, sizeof(*flash));
		if(rsize == sizeof(*flash))//读取正常
		{
			int fd, size;

			fd = open(DEVINFO_CFG_BAT, O_RDWR | O_CREAT | O_TRUNC);
			if(fd >= 0)//打开成功
			{
				size = write(fd,flash,sizeof(*flash));
				if(size == sizeof(*flash))//写成功
				{
					rt_kprintf("sizeof(*flash) = %d\r\n",sizeof(*flash));
				}
				close(fd);
			}
		}
	}
	else
	{
		LOG_E("Fal %s partition none find!!!!!!!!!!!!!",FAL_DEVINFO_NAME);
	}

	rt_free(flash);
}

void save_devinfo(void)
{
	struct fal_partition *fal;
	devInfoDef           *info;
	devInfoStoreDef      *flash;

	flash = rt_calloc(1, sizeof(*flash));
	RT_ASSERT(flash);

	info = devInfo_take();
	devinfo_release();

	info->saveFlag = DEVINFO_SAVE_FLAG;
	rt_memcpy(&(flash->arg),info,sizeof(*info));//拷贝数据
	
	fal = fal_partition_find(FAL_DEVINFO_NAME);
	RT_ASSERT(fal);
	rt_kprintf("find %s device %s partition %dKB\r\n",fal->flash_name,fal->name,fal->len/1024);

	fal_partition_erase_all(fal);
	rt_kprintf("erase end\r\n");
	store_crc_get(&(flash->stor));//计算CRC
	rt_kprintf("save devInfo crc=%x\r\n\r\n",flash->stor.crc16);

	int wsize = fal_partition_write(fal, 0, flash, sizeof(*flash));
	if(wsize == sizeof(*flash))
	{
		copy_info_to_file();
	}

	rt_free(flash);
}



void load_devinfo(void)
{
	struct fal_partition *fal;
	devInfoDef *info;
	rt_uint16_t crc16;
	devInfoStoreDef      *flash;
	
	LOG_I("devInfoDef=%d\r\n",sizeof(*info));

	flash = rt_calloc(1, sizeof(*flash));
	RT_ASSERT(flash);
	
	info = devInfo_take();
	devinfo_release();
	
	fal = fal_partition_find(FAL_DEVINFO_NAME);
	RT_ASSERT(fal);

	fal_partition_read(fal, 0, (uint32_t *)flash, sizeof(*flash));//读取数据
	crc16 = flash->stor.crc16;
	store_crc_get(&(flash->stor));//计算CRC
	if(crc16 != flash->stor.crc16)//参数错误
	{
		int fd, size;

		LOG_W("Fal crc=%X != %X=flash->stor.crc16 !!!!!!!!!!!!",flash->stor.crc16);
		
		fd = open(DEVINFO_CFG_BAT, O_RDWR);
		if(fd >= 0)//打开文件成功
		{	
			rt_uint16_t crc16;

			rt_memset(flash,0,sizeof(*flash));
			read(fd,flash,sizeof(*flash));

			crc16 = flash->stor.crc16;
			store_crc_get(&(flash->stor));

			if(crc16 == flash->stor.crc16)
			{
				LOG_W("USEING %s device config file !!!");
				rt_memcpy(info,&(flash->arg),sizeof(*info));
			}
			else
			{
				devInfo_init();
				LOG_E("load_devinfo CRC err %x != %x,using default config",crc16,flash->stor.crc16);
			}

			close(fd);
			rt_kprintf("load %s file ok ^_^\r\n",DEVINFO_CFG_BAT);
		}
		else
		{
			devInfo_init();
			LOG_E("reinit devinfo!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!");
		}
	}
	else
	{
		rt_memcpy(info,&(flash->arg),sizeof(*info));
	}
	LOG_I("find %s device %s partition devInfo crc16=%x crc16=%X\r\n",fal->flash_name,fal->name,flash->stor.crc16,crc16);
	show_devinfo();

	rt_free(flash);
}


/* ----------------------------------------------------------------------------*/
/**
 * @brief get_mcu_mac       获取MAC地址
 */
/* ----------------------------------------------------------------------------*/
void get_mcu_mac(void)
{
	devInfoDef *info;
	rt_uint32_t mac[3];
	
	info = devInfo_take();

	mac[0] = *(volatile rt_uint32_t*)(0x1FFF7A10);
	mac[1] = *(volatile rt_uint32_t*)(0x1FFF7A14);
	mac[2] = *(volatile rt_uint32_t*)(0x1FFF7A18);
	rt_sprintf(info->mac,"%08X%08X%08X",mac[0],mac[1],mac[2]);
	//rt_kprintf("info->mac=%s\r\n",info->mac);
	
	devinfo_release();
}


rt_uint8_t gsmCsqString[32];

/* --------------------------------------------------------------------------*/
/**
 * @Synopsis  解析获取gsm的信号值
 *
 * @Param buf AT+CSQ指令的返回字符串
 *
 * @Returns   信号质量 0-30
 */
/* ----------------------------------------------------------------------------*/
rt_int8_t get_gsm_CSQ(void)
{
  rt_int8_t csq;
  rt_uint8_t *head,*end;
  rt_uint8_t str[3] = {0};
	rt_uint8_t *buf;

	buf = gsmCsqString;

  if(rt_strstr((const char *)buf,",99") != NULL)
  {
  	head = buf;
    end = (rt_uint8_t *)rt_strstr((const char *)buf,",99");
    //srt_kprintf("head:%s\n",head);
    //rt_kprintf("head:%s\n",end);
    if(head != NULL && end != RT_NULL)
    {
      if((end - head > 0) && (end - head < 3))
      {
        rt_memcpy(str, head, end - head);
        //rt_kprintf("csq %d\n",atoi((const char *)str));
        csq = atoi((const char *)str);
      }
      else
      {
        csq = 0;//没有返回
      }
    }
    else
    {
      csq = 0;
    }
  }
  else
  {
    //rt_kprintf("none csq\n");
    csq = 0;
  }
  return csq;
} 



